<!--
  To test this file, you need to use a local server. The recommendation is that you run:

    npx serve .

  Then open http://localhost:5000/test/custom-worker
-->

<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
	</head>
	<body>
		<h2>Monaco Editor TypeScript test page</h2>
		<button id="resetBtn">Reset Sample</button>
		<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
		<h3>Custom webworker</h3>
		<button id="logDTS">Log DTS</button>
		<button id="getAST">Print AST to console</button>

		<script src="../dev-setup.js"></script>

		<script>
			function getDefaultCode() {
				return [
					'/* Game of Life',
					' * Implemented in TypeScript',
					' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
					' */',
					'',
					'module Conway {',
					'',
					'	export class Cell {',
					'		public row: number;',
					'		public col: number;',
					'		public live: boolean;',
					'',
					'		constructor(row: number, col: number, live: boolean) {',
					'			this.row = row;',
					'			this.col = col;',
					'			this.live = live',
					'		}',
					'	}',
					'',
					'	export class GameOfLife {',
					'		private gridSize: number;',
					'		private canvasSize: number;',
					'		private lineColor: string;',
					'		private liveColor: string;',
					'		private deadColor: string;',
					'		private initialLifeProbability: number;',
					'		private animationRate: number;',
					'		private cellSize: number;',
					'		private context: CanvasRenderingContext2D;',
					'		private world;',
					'',
					'',
					'		constructor() {',
					'			this.gridSize = 50;',
					'			this.canvasSize = 600;',
					"			this.lineColor = '#cdcdcd';",
					"			this.liveColor = '#666';",
					"			this.deadColor = '#eee';",
					'			this.initialLifeProbability = 0.5;',
					'			this.animationRate = 60;',
					'			this.cellSize = 0;',
					'			this.world = this.createWorld();',
					'			this.circleOfLife();',
					'		}',
					'',
					'		public createWorld() {',
					'			return this.travelWorld( (cell : Cell) =>  {',
					'				cell.live = Math.random() < this.initialLifeProbability;',
					'				return cell;',
					'			});',
					'		}',
					'',
					'		public circleOfLife() : void {',
					'			this.world = this.travelWorld( (cell: Cell) => {',
					'				cell = this.world[cell.row][cell.col];',
					'				this.draw(cell);',
					'				return this.resolveNextGeneration(cell);',
					'			});',
					'			setTimeout( () => {this.circleOfLife()}, this.animationRate);',
					'		}',
					'',
					'		public resolveNextGeneration(cell : Cell) {',
					'			var count = this.countNeighbors(cell);',
					'			var newCell = new Cell(cell.row, cell.col, cell.live);',
					'			if(count < 2 || count > 3) newCell.live = false;',
					'			else if(count == 3) newCell.live = true;',
					'			return newCell;',
					'		}',
					'',
					'		public countNeighbors(cell : Cell) {',
					'			var neighbors = 0;',
					'			for(var row = -1; row <=1; row++) {',
					'				for(var col = -1; col <= 1; col++) {',
					'					if(row == 0 && col == 0) continue;',
					'					if(this.isAlive(cell.row + row, cell.col + col)) {',
					'						neighbors++;',
					'					}',
					'				}',
					'			}',
					'			return neighbors;',
					'		}',
					'',
					'		public isAlive(row : number, col : number) {',
					'			if(row < 0 || col < 0 || row >= this.gridSize || col >= this.gridSize) return false;',
					'			return this.world[row][col].live;',
					'		}',
					'',
					'		public travelWorld(callback) {',
					'			var result = [];',
					'			for(var row = 0; row < this.gridSize; row++) {',
					'				var rowData = [];',
					'				for(var col = 0; col < this.gridSize; col++) {',
					'					rowData.push(callback(new Cell(row, col, false)));',
					'				}',
					'				result.push(rowData);',
					'			}',
					'			return result;',
					'		}',
					'',
					'		public draw(cell : Cell) {',
					'			if(this.context == null) this.context = this.createDrawingContext();',
					'			if(this.cellSize == 0) this.cellSize = this.canvasSize/this.gridSize;',
					'',
					'			this.context.strokeStyle = this.lineColor;',
					'			this.context.strokeRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
					'			this.context.fillStyle = cell.live ? this.liveColor : this.deadColor;',
					'			this.context.fillRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
					'		}',
					'',
					'		public createDrawingContext() {',
					"			var canvas = <HTMLCanvasElement> document.getElementById('conway-canvas');",
					'			if(canvas == null) {',
					"					canvas = document.createElement('canvas');",
					"					canvas.id = 'conway-canvas';",
					'					canvas.width = this.canvasSize;',
					'					canvas.height = this.canvasSize;',
					'					document.body.appendChild(canvas);',
					'			}',
					"			return canvas.getContext('2d');",
					'		}',
					'	}',
					'}',
					'',
					'var game = new Conway.GameOfLife();'
				].join('\n');
			}

			function getDefaultComplierOpts() {
				return { target: 99, jsx: 1, allowNonTsExtensions: true };
			}
			loadEditor(() => {
				const dirname = (path) => {
					const slashIndex = path.lastIndexOf('/');
					if (slashIndex >= 0) {
						return path.substring(0, slashIndex);
					}
					return path;
				};
				const customWorkerPath = `${dirname(location.href)}/custom-worker.js`;
				monaco.languages.typescript.typescriptDefaults.setWorkerOptions({
					customWorkerPath: customWorkerPath
				});
				monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
					target: 99,
					jsx: 1,
					allowNonTsExtensions: true,
					declaration: true,
					noLibCheck: true
				});

				var editor = monaco.editor.create(document.getElementById('container'), {
					value: localStorage.getItem('code') || getDefaultCode(),
					language: 'typescript',
					lightbulb: { enabled: true }
				});

				editor.onDidChangeModelContent(() => {
					const code = editor.getModel().getValue();
					localStorage.setItem('code', code);
				});

				document.getElementById('resetBtn').onclick = () => {
					editor.setValue(getDefaultCode());
				};

				document.getElementById('logDTS').onclick = async () => {
					const model = editor.getModel();
					const worker = await monaco.languages.typescript.getTypeScriptWorker();
					const thisWorker = await worker(model.uri);
					const dts = await thisWorker.getDTSEmitForFile(model.uri.toString());
					console.log(dts);
				};

				document.getElementById('getAST').onclick = async () => {
					const model = editor.getModel();
					const worker = await monaco.languages.typescript.getTypeScriptWorker();
					const thisWorker = await worker(model.uri);
					const ast = await thisWorker.printAST(model.uri.toString());
					console.log(ast);
				};
			});
		</script>
	</body>
</html>
